package com.ideaction.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class TimeUtil {
    
    public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getDefault();
    
    /**
     * 时间差
     */
    public static final int RAW_OFFSET_MILLISECONDS = DEFAULT_TIME_ZONE.getRawOffset();
    
    /**
     * 每天周毫秒数
     */
    public static final long PER_WEEK_DAY_MILLISECONDS = 604800000;
    
    // 周一为一周的开始
    private static final int WEEK_DAY_OFFSET = 4;
    
    /**
     * 每天毫秒数
     */
    public static final long PER_DAY_MILLISECONDS = 86400000;
    
    /**
     * 指定的时间戳（毫秒）是否与目标时间戳（秒）为同一周
     */
    public static boolean isSameWeek(long timeMillis, long targetTimeMillis) {
        long startTimes = getWeekStartMillis(targetTimeMillis);
        return timeMillis >= startTimes && timeMillis < (startTimes + PER_WEEK_DAY_MILLISECONDS);
    }
    
    public static long getWeekStartMillis(long timeMillis) {
        int days = (int) ((timeMillis + RAW_OFFSET_MILLISECONDS) / PER_DAY_MILLISECONDS);
        int offset = days % 7 - WEEK_DAY_OFFSET;
        if (offset < 0) {
            offset = 7 + offset;
        }
        return days * PER_DAY_MILLISECONDS - RAW_OFFSET_MILLISECONDS - offset * PER_DAY_MILLISECONDS;
    }
    
    /**
     * 是否同一天
     *
     * @param time
     * @param time2
     * @return
     */
    public static boolean isSameDay(long time, long time2, int timeZone) {
        Calendar instance = Calendar.getInstance();
        instance.setTimeInMillis(time);
        instance.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        int d1 = instance.get(Calendar.DAY_OF_YEAR);
        int y1 = instance.get(Calendar.YEAR);
        
        instance.setTimeInMillis(time2);
        instance.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        int d2 = instance.get(Calendar.DAY_OF_YEAR);
        int y2 = instance.get(Calendar.YEAR);
        return d1 == d2 && y1 == y2;
    }
    
    public static boolean crossDay(long time1, long time2, int hour, int timeZone) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        cal.setTimeInMillis(time1);
        
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        
        if (cal.getTimeInMillis() <= time1) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
        }
        return time2 > cal.getTimeInMillis();
    }
    
    public static boolean freshTime(List<Integer> freshTimeList, long lastFreshTime, long buyTime, int timeZone) {
        // 跨天重置
        if (!isSameDay(lastFreshTime, buyTime, timeZone)) {
            return true;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(lastFreshTime);
        cal.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        int lastHour = cal.get(Calendar.HOUR_OF_DAY);
        int lastArea = 24;
        for (int freshHour : freshTimeList) {
            if (lastHour < freshHour) {
                lastArea = freshHour;
                break;
            }
        }
        Calendar cal2 = Calendar.getInstance();
        cal2.setTimeInMillis(buyTime);
        cal2.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        int nowHour = cal2.get(Calendar.HOUR_OF_DAY);
        int nowArea = 24;
        for (int freshHour : freshTimeList) {
            if (nowHour < freshHour) {
                nowArea = freshHour;
                break;
            }
        }
        // 在同一区间,不刷新
        if (lastArea == nowArea) {
            return false;
        }
        
        return true;
    }
    
    //	public static boolean canRefresh(List<Integer> freshTimeList, long lastFreshTime) {
    //		int first = freshTimeList.get(0);
    //		if (crossDay(lastFreshTime, System.currentTimeMillis(), first)) {
    //			return true;
    //		} else {
    //
    //			Calendar cal = Calendar.getInstance();
    //			cal.setTimeInMillis(lastFreshTime);
    //			int hour = cal.get(Calendar.HOUR_OF_DAY);
    //			if (hour >= freshTimeList.get(freshTimeList.size() - 1)) {
    //				return false;
    //			}
    //
    //			for (int i = 1; i < freshTimeList.size(); i++) {
    //				int begin = freshTimeList.get(i - 1);
    //				int end = freshTimeList.get(i);
    //				int area = end - begin;
    //				boolean same = (hour - begin) / area == (getHour() - begin) / area;
    //				if (same) {
    //					return false;
    //				}
    //
    //			}
    //		}
    //		return true;
    //	}
    
    public static int getHour() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(1614162323000l);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        return hour;
    }
    
    public static List<Integer> getTimeList(String timeStr) {
        List<Integer> freshTimeList = new ArrayList<>();
        String[] timeStrAry = timeStr.split(",");
        for (String str : timeStrAry) {
            freshTimeList.add(Integer.parseInt(str));
        }
        return freshTimeList;
    }
    
    public static long getNextDayZero(int timeZone) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        cal.set(Calendar.HOUR_OF_DAY, 24);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }
    
    public static long getNextWeekZero(int timeZone) {
        //获得入参的日期
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone(getZoneId(timeZone)));
        // 获得入参日期是一周的第几天
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        // 获得入参日期相对于下周一的偏移量（在国外，星期一是一周的第二天，所以下周一是这周的第九天）
        // 若入参日期是周日，它的下周一偏移量是1
        int nextMondayOffset = dayOfWeek == 1 ? 1 : 9 - dayOfWeek;
        // 增加到入参日期的下周一
        cal.add(Calendar.DAY_OF_MONTH, nextMondayOffset);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }
    
    public static String getZoneId(int timeZone) {
        String zoneId = "Etc/GMT";
        if (timeZone >= 0) {
            zoneId += "-" + timeZone;
        } else {
            zoneId += "+" + -timeZone;
        }
        return zoneId;
    }
    
    /**
     * 将String格式的日期转换成Data
     *
     * @param birthDay
     * @return
     * @throws IllegalArgumentException
     */
    public static int getAgeByBirth(String birthDay) throws IllegalArgumentException {
	    if (birthDay == null || "".equals(birthDay)) {
		    return 0;
	    }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");//Date指定格式：yyyy-MM-dd
        Date date = new Date();//创建一个date对象保存当前时间
        try {
            date = simpleDateFormat.parse(birthDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return getAgeByBirth(date);
    }
    
    /**
     * 根据出生日期计算年龄
     *
     * @param birthDay
     * @return
     * @throws IllegalArgumentException
     */
    public static int getAgeByBirth(Date birthDay) throws IllegalArgumentException {
        int age;
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) { //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException("The birthDay is before Now.It's unbelievable!");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;//当前日期在生日之前，年龄减一
                }
            } else {
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }
    
    public static void main(String[] args) {
        long time = getNextDayZero(-4);
    }
}
